package org.mics.core.interceptor;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;


/**
 * 请求参数处理
 * @author mics
 * @date 2022-6-15
 * @version  1.0
 */
public class ParameterRequestWrapper extends HttpServletRequestWrapper {
	 private Map<String , String[]> params = new HashMap<String, String[]>();    
	 private static final Logger LOGGER = LoggerFactory.getLogger(ParameterRequestWrapper.class);
	  
	  public ParameterRequestWrapper(HttpServletRequest request) {    
	      super(request);   
	      //将参数表，赋予给当前的Map以便于持有request中的参数    
	      Map<String, String[]> requestMap=request.getParameterMap();
	      this.params.putAll(requestMap);
	      this.modifyParameterValues();
	  }    
	  
	  /**
	   * 将parameter的值去除空格后重写回去 
	   */
	  public void modifyParameterValues(){
	      Set<String> set =params.keySet();    
	      Iterator<String> it=set.iterator();    
	      while(it.hasNext()){    
	         String key= (String) it.next();    
	         String[] values = params.get(key);    
	         values[0] = values[0].trim();    
	         params.put(key, values);    
	       }    
	  }   
	  
	  /**
	   * 重写getInputStream方法  post类型的请求参数必须通过流才能获取到值
	   */
	  @Override
	  public ServletInputStream getInputStream() throws IOException {
	        //非json类型，直接返回
	        if(!super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)){
	            return super.getInputStream();
	        }
	        //为空，直接返回
	        String json = IOUtils.toString(super.getInputStream(), "utf-8");
	        if (!StringUtils.hasText(json)) {
	            return super.getInputStream();
	        }
	        try {
				Map<?,?> map=jsonStringToMap(json);
				json=JSON.toJSONString(map);
	    	}catch (Exception e) {
	    		LOGGER.info("不是标准json参数不处理空格"+json);
			}			
	        ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8"));
	        return new MyServletInputStream(bis);
	  }
	  
	   
	  
	  @Override
	    public String[] getParameterValues(String name) {
	        return params.get(name);
	    }

	    class MyServletInputStream extends ServletInputStream {
	        private ByteArrayInputStream bis;
	        public MyServletInputStream(ByteArrayInputStream bis){
	            this.bis=bis;
	        }
	        @Override
	        public boolean isFinished() {
	            return true;
	        }

	        @Override
	        public boolean isReady() {
	            return true;
	        }

	        @Override
	        public void setReadListener(ReadListener listener) {

	        }
	        @Override
	        public int read(){
	            return bis.read();
	        }
	    }

	    public static Map<String, Object> jsonStringToMap(String jsonString) {
    		Map<String, Object> map = new HashMap<>();
 	        JSONObject jsonObject = JSONObject.parseObject(jsonString);
  	        for (Object k : jsonObject.keySet()) {
 	            Object o = jsonObject.get(k);
 	            if (o instanceof JSONArray) {
 	                List<Object> list = new ArrayList<>();
 	                Iterator<Object> it = ((JSONArray) o).iterator();
 	                while (it.hasNext()) {
 	                    Object obj = it.next();
 	                    if (obj instanceof JSONObject){
 	                    	Map<?,?> result = jsonStringToMap(obj.toString());
 	                        list.add(result);
 	                    }else if (obj instanceof String) {
 	                       list.add(obj.toString().trim());
 	                    } else {
 	                        list.add(obj);
 	                    }
 	                }
 	                map.put(k.toString(), list);
 	            } else if (o instanceof JSONObject) {
 	                map.put(k.toString(), jsonStringToMap(o.toString()));
 	            } else {
 	                if (o instanceof String) {
 	                    map.put(k.toString(), o.toString().trim());
 	                } else {
 	                    map.put(k.toString(), o);
 	                }
 	            }
 	        }
 	        return map;
	    }
}